/*
 * Project: Sudoku Hint Engine for Android
 * Copyright (C) 2010-2013 Emanuel Moecklin
 * 
 * Available under the terms of the Lesser General Public License (LGPL)
 */
package com.onegravity.sudoku.solver.checks;

import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import android.net.Uri;

import com.onegravity.sudoku.solver.HintResource;
import com.onegravity.sudoku.solver.HintType;
import com.onegravity.sudoku.solver.core.FinalHint;
import com.onegravity.sudoku.solver.core.IndirectHint;
import com.onegravity.sudoku.solver.core.Rule;
import com.onegravity.sudoku.solver.data.Cell;
import com.onegravity.sudoku.solver.data.Grid;
import com.onegravity.sudoku.solver.util.BitSetIterator;
import com.onegravity.sudoku.solver.util.HtmlLoader;
import com.onegravity.sudoku.solver.util.Link;

/**
 * Indicates that the puzzle has no pencil marks at all and allows to set them (apply()).
 * @author Emanuel Moecklin
 */
public class MissingPencilMarksHint extends IndirectHint implements Rule, FinalHint {

	private static final long serialVersionUID = -4302698125420567427L;
	
	private Map<Cell, BitSet> toBeAdded;
	
	public MissingPencilMarksHint(Map<Cell, BitSet> toBeAddedNew) {
		super(toBeAddedNew);
		this.toBeAdded = (toBeAddedNew==null) ? new HashMap<Cell, BitSet>() : toBeAddedNew;
	}

	@Override
    public Grid apply() {
    	Grid theGrid = null;
		BitSetIterator<Integer> it = new BitSetIterator<Integer>();
		for (Cell cell:toBeAdded.keySet()) {
        	theGrid = (theGrid==null) ? cell.getGrid() : theGrid; 
			for (it.restart(toBeAdded.get(cell)); it.hasNext(); ) {
				int value = it.next();
				cell.addPotentialValue(value);
			}
		}
		return theGrid;
	}

    @Override
	public String getName() {
		return HintResource.MISSING_PENCIL_MARKS.getName();
	}

    @Override
    public Uri getLink() {
		return HintResource.MISSING_PENCIL_MARKS.getUrl();
    }

	@Override
	public double getDifficulty() {
		return 0;
	}

	@Override
	public String toString() {
		String cellStringNewlyAdded = Cell.toString(toBeAdded.keySet().toArray(new Cell[toBeAdded.size()]));
		return HintResource.MISSING_PENCIL_MARKS.toString(cellStringNewlyAdded); 
	}

	@Override
	public String getHintHtml(HintType type) {
		String result = HtmlLoader.loadHtml(HintResource.MISSING_PENCIL_MARKS.hint(type));
        return HtmlLoader.format(result, toBeAdded.size(), count(toBeAdded.values()));
	}
	
	private int count(Collection<BitSet> data) {
		int counter = 0;
		for (BitSet tmp:data) {
			counter += tmp.cardinality();
		}
		return counter;
	}

	@Override
    public Map<Cell, BitSet> getAddedPotentials(HintType type, int viewNum) {
        return (type==HintType.BIG_CLUE) ? toBeAdded : null;
    }

    public int getNrOfSteps() {
    	return 2;
    }

	@Override
	public Collection<Link> getLinks(HintType type, int viewNum) {
		return null;
	}
}